package fjj

import scala.io.{Codec, Source}

import org.apache.commons.lang3.StringUtils

import us.hebi.matlab.mat.format.Mat5
import us.hebi.matlab.mat.types.{Matrix, Sinks}

object StiffnessMatrixReader {
  def main(args: Array[String]): Unit = {
    val matFile = readText(args(0))
    val sink = Sinks.newStreamingFile(args(1))
    matFile.writeTo(sink)
  }

  def readText(path: String) = {

    val matFile = Mat5.newMatFile()

    val buffer = Source.fromFile(path)(Codec.UTF8)

    val (lastId, lastMatrix, _) = buffer
      .getLines()
      .map(_.trim)
      .foldLeft(("", None: Option[Matrix], 0)) {
        case (t @ (id, matrixOpt, row), line) =>
          if (StringUtils.isBlank(line)) t
          else if (line.contains("STIFFNESS MATRIX FOR ELEMENT")) {
            val element = line.split("\\s+").last
            if (matrixOpt.nonEmpty) matFile.addArray(id, matrixOpt.get)
            val matrix = Mat5.newMatrix(8, 8)
            (s"e$element", Some(matrix), -1)
          } else if (matrixOpt.nonEmpty &&
            StringUtils.isNumericSpace(line.replaceAll("[-+E.]", ""))) {
            val cols = line.split("\\s+", 9)
            if (cols.head >= "1" && cols.head <= "8") {
              val row = cols.head.toInt
              cols.tail.map(_.toDouble).zipWithIndex.foreach {
                case (v, i) =>
                  matrixOpt.get.setDouble(row - 1, i, v)
              }
              t.copy(_3 = row)
            } else {
              val values = cols.map(_.toDouble).zipWithIndex
              values.foreach {
                case (v, i) =>
                  matrixOpt.get.setDouble(row - 1, i + 6, v)
              }
              t
            }
          } else t
      }

    buffer.close()

    if (StringUtils.isNotBlank(lastId)) {
      matFile.addArray(lastId, lastMatrix.get)
    }
    matFile
  }
}
